home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #6 / Amiga Plus CD - 2004 - No. 06.iso / AmiSoft / Comm / misc / trsi-ftpd01.lha / FAME-FTPd / source / famesupport.c < prev    next >
C/C++ Source or Header  |  2004-04-24  |  22KB  |  655 lines

  1. /****************************************************************************************
  2.  *  PROJECT: FAME-FTPd
  3.  *     FILE: famesupport.c
  4.  *  PURPOSE: FAME-related functions like username/pw validation & File Management
  5.  *  CREATED: 05-MAY-2003
  6.  * MODIFIED: 21-JAN-2004
  7.  *   AUTHOR: Sascha 'SieGeL' Pfalz
  8.  ****************************************************************************************/
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/dos.h>
  12. #include <proto/locale.h>
  13. #include <proto/utility.h>
  14. #include <proto/fame.h>
  15. #include <libraries/fame.h>
  16. #include <fame/fame.h>
  17.  
  18. #include <sys/types.h>
  19. #include <sys/syslog.h>
  20. #include <sys/socket.h>
  21. #include <sys/errno.h>
  22. #include <sys/param.h>
  23. #include <sys/stat.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/file.h>
  26. #include <sys/wait.h>
  27. #include <sys/errno.h>
  28. #include <error.h>
  29. #include <proto/socket.h>
  30. #include <netinet/in.h>
  31. #include <amitcp/socketbasetags.h>
  32. #include <netdb.h>
  33.  
  34. #include "version.h"
  35. #include "proto.h"
  36. #include "ftp.h"
  37. #include "struct_ex.h"
  38.  
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. static  char uname[]="FAME-FTPd",udesc[]="FAME FTP Server";
  43.  
  44. /*************************************************************************************************
  45.  * Prototypes
  46.  *************************************************************************************************/
  47.  
  48. BOOL                 ValidateFameUser(char *username, char *password, struct FTP *ftp);
  49. long                 RetrieveFAMEInfos(void);
  50. static long ParseConferences(char *confaxs);
  51. BOOL                 AddConference(struct FAMEConf *, long confnumber);
  52. void                 FreeConferenceList(void);
  53. BOOL                AddFileToUList(char *fullname, long fsize, long cnum,struct FTP *ftp,char *tempname);
  54. BOOL                 CheckForDoubles(char *fullname, long confnum);
  55. long                 GetConfNumber(char *confname);
  56. BOOL                 UpdateUserStats(long confnumber, struct FTP *ftp, ULONG bytes, long files);
  57. BOOL                 CheckIfOnline(long unumcheck);
  58.  
  59. /*************************************************************************************************
  60.  *     FUNCTION: RetrieveFAMEInfos()
  61.  *      PURPOSE: Reads FAME infos like BBS Path, Sysop etc.
  62.  * REQUIREMENTS: FAME must be started!
  63.  *        INPUT: -
  64.  *       RETURN: 0 => OK | -1 => FAME not running
  65.  *        NOTES: Must be called BEFORE ValidateFAMEUser(), else system crashes!
  66.  *************************************************************************************************/
  67.  
  68. long RetrieveFAMEInfos(void)
  69.     {
  70.     struct  FAMESemaphore *MyFAMESemaphore;
  71.  
  72.     FAMEMemSet(FameInfo,0,sizeof(struct FAMEInfos));
  73.      Forbid();
  74.     if(MyFAMESemaphore=(struct FAMESemaphore *)FindSemaphore("FAMESemaphore"))
  75.         {
  76.         ObtainSemaphore((struct SignalSemaphore *)MyFAMESemaphore);
  77.     FAMEStrCopy(MyFAMESemaphore->fsem_SVBBSName,FameInfo->BBSName,255);
  78.         FameInfo->FAMEVersion = MyFAMESemaphore->fsem_SVVersion;
  79.         FameInfo->FAMERevision = MyFAMESemaphore->fsem_SVRevision;
  80.         Permit();
  81.         ReleaseSemaphore((struct SignalSemaphore *)MyFAMESemaphore);
  82.         return(0);
  83.       }
  84.   else
  85.         {
  86.         Permit();
  87.         return(-1);        // FAME not running !
  88.         }
  89.     }
  90.  
  91. /*************************************************************************************************
  92.  *     FUNCTION: ValidateFAMEUser()
  93.  *      PURPOSE: Checks if given user/password is valid/known to FAME and if given data are
  94.  *               correct the conference list will be loaded and stored in memory.
  95.  * REQUIREMENTS: FAME must be started!
  96.  *        INPUT: username => Name of user
  97.  *               password => Password of user
  98.  *                    ftp => Master FTP struct
  99.  *       RETURN: TRUE = User is valid and loaded | FALSE = User unknown/wrong PW
  100.  *************************************************************************************************/
  101.  
  102. BOOL ValidateFAMEUser(char *username, char *password,struct FTP *ftp)
  103.     {
  104.   struct    FAMEConfigRequest *fcr;
  105.   struct    FAMEUser                    *myuserdata;
  106.     struct     FAMEConfAccess         *mycfgaxs;
  107.     struct  FAMESystem                *mysystem;
  108.     struct    FAMELevels                *mylevel;
  109.     long        myresult=0,rc2;
  110.     char        errbuf[256],axs[22];
  111.     static    char funcname[] = "ValidateFAMEUser";
  112.     long        templevel = -1;
  113.  
  114.     if(!*username)
  115.         {
  116.         DebugLog("LOGIN: No username given - login denied!");
  117.         return(FALSE);
  118.         }
  119.   fcr = AllocPooled(mem_pool,sizeof(struct FAMEConfigRequest));
  120.     if(!fcr)
  121.         {
  122.     fail(ERROR_NO_FREE_STORE,"%s: Unable to allocate fcr struct!",funcname);
  123.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  124.          return(FALSE);
  125.         }
  126.     FAMERequestReset(fcr);
  127.     fcr->fcr_CfgUserTask         = FindTask(NULL);
  128.     fcr->fcr_CfgUserName         = uname;
  129.     fcr->fcr_CfgUserDesc         = udesc;
  130.   fcr->fcr_ConfigType          = FCDD_User;                            // We want the FAME user.data
  131.     fcr->fcr_ConfigMode          = FAMECFG_MODE_READ;             // Nothing will be changed here!
  132.   fcr->fcr_SearchOffset     = 0;                                            // Search for the Username in user.data
  133.     fcr->fcr_SearchValue        = username;                   // search for given Username
  134.     fcr->fcr_SearchType        = FAMECFGVARTYPE_STRING;  // We want string compare
  135.     fcr->fcr_SearchOperator    = FAMECFGOP_EQUAL;                // Username must match!
  136.     myuserdata = FAMEObtainConfig(fcr,&myresult);
  137.     if(myuserdata)
  138.         {
  139.         if(!Stricmp(password,myuserdata->Password))
  140.             {
  141.             myresult = FAMECFGRES_SUCCESS;
  142.             ftp->usernumber = myuserdata->UserNumber;
  143.       FAMEStrCopy(myuserdata->ConfAccess,axs,21);
  144.             }
  145.         else
  146.             {
  147.             myresult = FAMECFGRES_SEARCHNOTFOUND;
  148.             DebugLog("LOGIN: Unknown User %s - Login denied!",username);
  149.             }
  150.     }
  151.  
  152.     /*
  153.    *  We check now if the user is allowed to login by checking his state:
  154.       */
  155.  
  156.   if(myresult==FAMECFGRES_SUCCESS)
  157.         {
  158.     if(myuserdata->Deleted_Or_Not)        // 0 means active, all others are forbidden
  159.             {
  160.             myresult = FAMECFGRES_SEARCHNOTFOUND;
  161.             }
  162.     else
  163.             {
  164.             templevel = myuserdata->Userlevel;        // Save level for further checking
  165.             }
  166.         }
  167.     FAMEReleaseConfig( myuserdata, FAMECFG_MODE_READ, FindTask( NULL ));
  168.     if(myresult == FAMECFGRES_SEARCHNOTFOUND) return(FALSE);
  169.     if(myresult != FAMECFGRES_SUCCESS)
  170.     {
  171.         FAMEHandleConfigResults(errbuf,myresult,FCDD_User);
  172.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  173.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  174.          return(FALSE);
  175.         }
  176.  
  177.     /*
  178.      *    Now we load the Level define for that user and check if he/she is allowed
  179.    *  to upload files.
  180.       */
  181.  
  182.     FAMERequestReset(fcr);
  183.     fcr->fcr_CfgUserTask = FindTask(NULL);
  184.     fcr->fcr_CfgUserName = uname;                                    // Tool name
  185.     fcr->fcr_CfgUserDesc = udesc;                                    // Tool description
  186.   fcr->fcr_ConfigType  = FCDD_Levels;                        // We want the level structure
  187.     fcr->fcr_ConfigMode  = FAMECFG_MODE_READ;         // Nothing will be changed here!
  188.     fcr->fcr_ConfigNum     = templevel;                            // Load Level Data for current user
  189.   mylevel = FAMEObtainConfig(fcr,&myresult);
  190.     if(mylevel)
  191.         {
  192.         if(mylevel->Upload) ftp->UserFlags |= UF_UPLOAD;    // Set UploadAllow Flag
  193.         }
  194.   else
  195.         {
  196.         FAMEHandleConfigResults(errbuf,myresult,FCDD_Levels);
  197.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  198.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  199.          return(FALSE);
  200.         }
  201.     FAMEReleaseConfig(mylevel, FAMECFG_MODE_READ, FindTask( NULL ));
  202.  
  203.     /*
  204.    *     User/Password/Level access is known and valid, now request conference
  205.    *  list for this user.
  206.      *     First we need to know how many conferences exists for this BBS:
  207.      */
  208.  
  209.     FAMERequestReset(fcr);
  210.     fcr->fcr_CfgUserTask = FindTask(NULL);
  211.     fcr->fcr_CfgUserName = uname;                                    // Tool name
  212.     fcr->fcr_CfgUserDesc = udesc;                                    // Tool description
  213.   fcr->fcr_ConfigType  = FCDD_System;                        // We want the system structure
  214.     fcr->fcr_ConfigMode  = FAMECFG_MODE_READ;         // Nothing will be changed here!
  215.     mysystem = FAMEObtainConfig(fcr,&myresult);
  216.     if(mysystem)
  217.         {
  218.         FameInfo->NodeCount = mysystem->NumberOfConfs;
  219.         FAMEStrCopy(mysystem->SysOpName,FameInfo->SysOp,31);
  220.         }
  221.   else
  222.         {
  223.         FAMEHandleConfigResults(errbuf,myresult,FCDD_System);
  224.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  225.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  226.          return(FALSE);
  227.         }
  228.     FAMEReleaseConfig(mysystem, FAMECFG_MODE_READ, FindTask( NULL ));
  229.  
  230.     /*
  231.    *     Number of conferences is known. Build up the access list for this user:
  232.    */
  233.  
  234.     FAMERequestReset(fcr);
  235.     fcr->fcr_CfgUserTask     = FindTask(NULL);
  236.     fcr->fcr_ConfigStr        = axs;                    // The conference access from FAMEUser->ConfAccess
  237.     fcr->fcr_CfgUserName     = uname;                                    // Tool name
  238.     fcr->fcr_CfgUserDesc     = udesc;                                    // Tool description
  239.   fcr->fcr_ConfigType      = FCDD_ConfAccess;                // We want the conference access array
  240.     fcr->fcr_ConfigMode      = FAMECFG_MODE_READ;             // Nothing will be changed here!
  241.     mycfgaxs = FAMEObtainConfig(fcr,&myresult);
  242.     if(mycfgaxs)
  243.       {
  244.         rc2 = ParseConferences(mycfgaxs->ConfFlags);
  245.         if(rc2)
  246.             {
  247.             FAMEHandleConfigResults(errbuf,rc2,FCDD_Conf);
  248.             DebugLog("%s: %s (%ld)",funcname,errbuf,rc2);
  249.             FAMEReleaseConfig(mycfgaxs,FAMECFG_MODE_READ,FindTask(NULL));
  250.             usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  251.             return(FALSE);
  252.           }
  253.         }
  254.   else
  255.         {
  256.         FAMEHandleConfigResults(errbuf,myresult,FCDD_UserConf);
  257.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  258.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  259.          return(FALSE);
  260.         }
  261.     FAMEReleaseConfig(mycfgaxs, FAMECFG_MODE_READ, FindTask( NULL ));
  262.     FreePooled(mem_pool,fcr,sizeof(struct FAMEConfigRequest));
  263.     return(TRUE);
  264.     }
  265.  
  266. /*************************************************************************************************
  267.  *     FUNCTION: ParseConferences()
  268.  *      PURPOSE: Reads FAME conference data
  269.  * REQUIREMENTS: Global list to hold the conference informations
  270.  *    CALLED BY: ValidateFAMEUser()
  271.  *        INPUT: XXX_X_XXX_ (ConfAccess array)
  272.  *       RETURN: 0 => OK else Returncode indicates failure
  273.  *************************************************************************************************/
  274.  
  275. static long ParseConferences(char *confaxs)
  276.     {
  277.   struct    FAMEConfigRequest *fcr2;
  278.     struct    FAMEConf    *fconf;
  279.     char         *b = confaxs;
  280.     long      confcnt = 0,res2 = 0;
  281.  
  282.   fcr2 = AllocPooled(mem_pool,sizeof(struct FAMEConfigRequest));
  283.     if(!fcr2) return(-1);
  284.     while(*b && confcnt < FameInfo->NodeCount)
  285.         {
  286.         if(*b == 'X')
  287.             {
  288.             FAMERequestReset(fcr2);
  289.             fcr2->fcr_CfgUserTask = FindTask(NULL);
  290.             fcr2->fcr_CfgUserName = uname;                                    // Tool name
  291.             fcr2->fcr_CfgUserDesc = udesc;                                    // Tool description
  292.       fcr2->fcr_ConfigNum   = confcnt+1;                            // Read data from this conference (cnfcount starts with 0!)
  293.               fcr2->fcr_ConfigType  = FCDD_Conf;                            // We want the conference data
  294.             fcr2->fcr_ConfigMode  = FAMECFG_MODE_READ;             // Nothing will be changed here!
  295.             fconf = FAMEObtainConfig(fcr2,&res2);
  296.       if(fconf)
  297.                 {
  298.                 AddConference(fconf,confcnt+1);
  299.                 }
  300.             else
  301.                 {
  302.                 FreePooled(mem_pool,fcr2,sizeof(struct FAMEConfigRequest));
  303.                 return(res2);
  304.         }
  305.             FAMEReleaseConfig(fconf,FAMECFG_MODE_READ,FindTask(NULL));
  306.             }
  307.         *b++;
  308.         confcnt++;
  309.         }
  310.     FreePooled(mem_pool,fcr2,sizeof(struct FAMEConfigRequest));
  311.   return(0);
  312.     }
  313.  
  314. /*************************************************************************************************
  315.  *     FUNCTION: AddConference()
  316.  *      PURPOSE: Adds new conference to global list FConf
  317.  * REQUIREMENTS: Global list FConf
  318.  *        INPUT: fc                    => Pointer to FAMEConf to add
  319.  *               confnumber    => Corrected Conference number
  320.  *       RETURN: TRUE = Entry added | FALSE = Out of memory
  321.  *************************************************************************************************/
  322.  
  323. BOOL AddConference(struct FAMEConf *fc, long confnumber)
  324.     {
  325.     if(!fconf1)
  326.         {
  327.         if(!(fconf1=(struct FConf *)AllocPooled(mem_pool,sizeof(struct FConf)))) return(FALSE);
  328.         fconf2=fconf1;
  329.         }
  330.     else
  331.         {
  332.         if(!(fconf2->next=(struct FConf *)AllocPooled(mem_pool,sizeof(struct FConf)))) return(FALSE);
  333.         fconf2=fconf2->next;
  334.         }
  335.     fconf2->next=NULL;
  336.     FAMEStrCopy(fc->ConfName,fconf2->ConfName,31);
  337.     FAMEStrCopy(fc->ConfLocation,fconf2->ConfLocation,101);
  338.     FAMEStrCopy(fc->UploadPath,fconf2->ULPath,101);
  339.     FAMEStrCopy(fc->DownloadPath,fconf2->DLPath,101);
  340.     FAMEStrCopy(fc->AddUlPaths,fconf2->AddULPath,101);
  341.     FAMEStrCopy(fc->AddDlPaths,fconf2->AddDLPath,101);
  342.   fconf2->ConfNumber = confnumber;
  343.     ConvertSpaces(fconf2->ConfName);
  344.     return(TRUE);
  345.     }
  346.  
  347. /*************************************************************************************************
  348.  *     FUNCTION: FreeConferenceList()
  349.  *      PURPOSE: Adds new conference to global list FConf
  350.  * REQUIREMENTS: Global list FConf
  351.  *        INPUT: -
  352.  *       RETURN: -
  353.  *************************************************************************************************/
  354.  
  355. void FreeConferenceList(void)
  356.     {
  357.     struct FConf *h;
  358.  
  359.     while(fconf1)
  360.         {
  361.         h=fconf1;
  362.         fconf1=fconf1->next;
  363.         FreePooled(mem_pool,h,sizeof(struct FConf));
  364.         }
  365.     fconf1=NULL;fconf2=NULL;
  366.     }
  367.  
  368. /*************************************************************************************************
  369.  *     FUNCTION: CheckForDoubles()
  370.  *      PURPOSE: Iterates through the filelist and searches for a given file already uploaded
  371.  *               Also checks the dirs for the given fame conference if a file with that name
  372.  *               already exists.
  373.  * REQUIREMENTS: FileUploads List must be initialized!
  374.  *        INPUT: fullname    => Full name of uploaded file
  375.  *               confnum  => Number of conference where we should check
  376.  *       RETURN: TRUE = File already exists. FALSE = File cannot be found in list
  377.  *************************************************************************************************/
  378.  
  379. BOOL CheckForDoubles(char *fullname,long confnum)
  380.     {
  381.   struct     FTPUploads     *f1;
  382.     struct    FConf       *cdata=fconf1;
  383.     BOOL    found=FALSE;
  384.  
  385.   for(f1=(struct FTPUploads *)filelist.mlh_Head;f1!=(struct FTPUploads *)&filelist.mlh_Tail;f1=(struct FTPUploads *)f1->Node.mln_Succ)
  386.          {
  387.         if(!Stricmp(f1->FileName,FilePart(fullname)) && f1->ConfNum == confnum)
  388.             {
  389.             found=TRUE;
  390.       break;
  391.             }
  392.       }
  393.     if(found==TRUE) return(found);
  394.  
  395.     // File was not found in session specific upload list, let's check now the other places:
  396.  
  397.   while(cdata)
  398.         {
  399.         if(confnum == cdata->ConfNumber) break;
  400.     cdata=cdata->next;
  401.         }
  402.   if(!cdata)
  403.         {
  404.         DebugLog("Conf ptr. is ZERO???");
  405.         return(TRUE);        // should not happen!
  406.         }
  407.     DebugLog("Location=%s\n1.ULPATH=%s\n1.DLPATH=%s\nn.ULPATH=%s\nn.DLPATH=%s",cdata->ConfLocation,cdata->ULPath,cdata->DLPath,cdata->AddULPath,cdata->AddDLPath);
  408.     return(found);
  409.     }
  410.  
  411. /*************************************************************************************************
  412.  *     FUNCTION: AddFileToUList()
  413.  *      PURPOSE: Adds new file to global upload list (using Exec() Lists) and copies the file
  414.  *               to the conference playpen directory.
  415.  * REQUIREMENTS: FileUploads List must be initialized, and file must be uploaded without errors!
  416.  *        INPUT: fullname    => Full name to uploaded file
  417.  *               fsize        => Size of File
  418.  *               cnum            => Conference Number
  419.  *       RETURN: -
  420.  *************************************************************************************************/
  421.  
  422. BOOL AddFileToUList(char *fullname, long fsize, long cnum, struct FTP *ftp, char *tempname)
  423.     {
  424.   struct     FTPUploads *myul;
  425.     struct  FConf    *fc = fconf1;
  426.     char        buf[256],playpen[256],partul[256],d[10],t[10];
  427.     BPTR        fp;
  428.     BOOL        retcode;
  429.  
  430.     if(!(myul = AllocPooled(mem_pool,sizeof(struct FTPUploads))))
  431.         {
  432.         return(FALSE);
  433.         }
  434.   FAMEStrCopy(FilePart(fullname),myul->FileName,127);
  435.     myul->FileSize = fsize;
  436.     myul->ConfNum  = cnum;
  437.     FormatStamp(NULL,myul->FileDate,myloc,TRUE);
  438.     AddTail((struct List *)&filelist, (struct Node *)myul);
  439.     while(fc)
  440.         {
  441.         if(fc->ConfNumber == cnum)
  442.             {
  443.             break;
  444.             }
  445.         fc=fc->next;
  446.         }
  447.     if(!fc)
  448.         {
  449.         RemTail((struct List *)&filelist);
  450.         return(FALSE);
  451.         }
  452.   FAMEStrCopy(fc->ConfLocation,playpen,255);
  453.   SPrintf(buf,"PlayPen/%s",myul->FileName);
  454.   AddPart(playpen,buf,255);
  455.     FAMEFillMem(buf,0,255);
  456.     FAMEStrCopy(fc->ConfLocation,partul,255);
  457.      SPrintf(buf,"LostCarrier/%s@%ld",myul->FileName,ftp->usernumber);
  458.     AddPart(partul,buf,255);
  459.     if(!(fp = Open(partul,MODE_NEWFILE)))
  460.         {
  461.         DebugLog("ERROR: Cannot open %s (IoErr()=%ld",playpen,IoErr());
  462.         RemTail((struct List *)&filelist);
  463.     return(FALSE);
  464.         }
  465.     FormatStamp(NULL,buf,NULL,FALSE);
  466.   FAMEStrMid(buf,d,1,8);
  467.     FAMEStrMid(buf,t,9,-1);
  468.     FPrintf(fp,"%s\n%lu\n%lu\n100\n%s\n%ld\n%s\n%s\n",myul->FileName,fsize,fsize,ftp->username,ftp->usernumber,d,t);
  469.     Close(fp);
  470.     retcode = FAMEDosMove(tempname,playpen,fconfig->FileBufferSize*1024,FDMF_KEEPDATA|FDMF_NODELETE);
  471.     if(retcode == FALSE)     /* Error while copying, so cleanup uploaded files */
  472.         {
  473.         DebugLog("AddUL(): DosMove() %s -> %s failed (%ld)",tempname,playpen,IoErr());
  474.         DeleteFile(tempname);
  475.         DeleteFile(playpen);
  476.         DeleteFile(partul);
  477.     }
  478.     else
  479.         {
  480.         UpdateUserStats(cnum,ftp,fsize,1);
  481.         }
  482.   return(retcode);
  483.     }
  484.  
  485. /*************************************************************************************************
  486.  *     FUNCTION: GetConfNumber()
  487.  *      PURPOSE: Returns number of conference of given conf name
  488.  *        INPUT: confname    => Name of conference
  489.  *       RETURN: Conf Number or 0 to indicate "conference not found"
  490.  *************************************************************************************************/
  491.  
  492. long GetConfNumber(char *confname)
  493.     {
  494.     struct    FConf *fc = fconf1;
  495.  
  496.     while(fc)
  497.         {
  498.     if(!Strnicmp(fc->ConfName,confname,strlen(fc->ConfName))) return(fc->ConfNumber);
  499.         fc = fc->next;
  500.         }
  501.     return(0);
  502.     }
  503.  
  504. /*************************************************************************************************
  505.  *     FUNCTION: UpdateUserStats()
  506.  *      PURPOSE: Updates FAME user.data with new uploaded bytes.
  507.  *        INPUT: confnumber    => Conference number
  508.  *               ftp                => Master FTP Structure
  509.  *               bytes            => Bytes to add
  510.  *               files            => Filecount to add
  511.  *       RETURN: TRUE = Success, FALSE = Failure while updating
  512.  *************************************************************************************************/
  513.  
  514. BOOL UpdateUserStats(long confnumber, struct FTP *ftp, ULONG bytes, long files)
  515.     {
  516.   struct    FAMEConfigRequest *fcr;
  517.   struct    FAMEUser                    *myuserdata;
  518.     struct    FAMEUserConf            *myuserconf;
  519.     long        myresult=0;
  520.     char        errbuf[256];
  521.     static    char funcname[] = "UpdateUserStats";
  522.     ULONG        newbytes[2];
  523.  
  524.   fcr = AllocPooled(mem_pool,sizeof(struct FAMEConfigRequest));
  525.     if(!fcr)
  526.         {
  527.     fail(ERROR_NO_FREE_STORE,"%s: Unable to allocate fcr struct!",funcname);
  528.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  529.          return(FALSE);
  530.         }
  531.     FAMERequestReset(fcr);
  532.     fcr->fcr_CfgUserTask         = FindTask(NULL);
  533.     fcr->fcr_CfgUserName         = uname;
  534.     fcr->fcr_CfgUserDesc         = udesc;
  535.   fcr->fcr_ConfigType          = FCDD_User;                            // We want the FAME user.data
  536.     fcr->fcr_ConfigMode          = FAMECFG_MODE_MODIFY;        // We have to update the datA
  537.     fcr->fcr_ConfigNum            = ftp->usernumber;                // Usernumber to load
  538.     myuserdata = FAMEObtainConfig(fcr,&myresult);
  539.     if(myresult != FAMECFGRES_SUCCESS)
  540.     {
  541.         FAMEHandleConfigResults(errbuf,myresult,FCDD_User);
  542.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  543.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  544.         FAMEReleaseConfig( myuserdata, FAMECFG_MODE_MODIFY, FindTask( NULL ));
  545.         FreePooled(mem_pool,fcr,sizeof(struct FAMEConfigRequest));
  546.          return(FALSE);
  547.         }
  548.   newbytes[0] = myuserdata->BytesUpHi;
  549.     newbytes[1] = myuserdata->BytesUpload;
  550.   FAMEAdd64(0UL,bytes,&newbytes);
  551.     myresult = FAMELockConfig(myuserdata);
  552.     if(myresult == FAMECFGRES_SUCCESS)
  553.         {
  554.         myuserdata->Uploads+=files;
  555.         myuserdata->BytesUpHi = newbytes[0];
  556.         myuserdata->BytesUpload = newbytes[1];
  557.         FAMEUnLockConfig(myuserdata);
  558.         }
  559.     else DebugLog("LockConfig(user) Failed");
  560.     myresult = FAMESaveConfig(myuserdata,FAMECFG_MODE_MODIFY);
  561.     if(myresult != FAMECFGRES_SUCCESS)
  562.         {
  563.         DebugLog("Error writing back user.data: %ld",myresult);
  564.         }
  565.     FAMEReleaseConfig( myuserdata, FAMECFG_MODE_MODIFY, FindTask( NULL ));
  566.  
  567.     /* Now update UserConf.data, too */
  568.  
  569.     FAMERequestReset(fcr);
  570.     fcr->fcr_CfgUserTask         = FindTask(NULL);
  571.     fcr->fcr_CfgUserName         = uname;
  572.     fcr->fcr_CfgUserDesc         = udesc;
  573.   fcr->fcr_ConfigType          = FCDD_UserConf;                    // We want the FAME user.data
  574.     fcr->fcr_ConfigMode          = FAMECFG_MODE_MODIFY;        // We have to update the datA
  575.     fcr->fcr_ConfigNum            = ftp->usernumber;                // Usernumber
  576.     fcr->fcr_ConfigNum2            = confnumber;                            // Conference number
  577.     myuserconf = FAMEObtainConfig(fcr,&myresult);
  578.     if(myresult != FAMECFGRES_SUCCESS)
  579.     {
  580.         FAMEHandleConfigResults(errbuf,myresult,FCDD_UserConf);
  581.         DebugLog("%s: %s (%ld)",funcname,errbuf,myresult);
  582.         usprintf(ftp->control,CRLF_NOSTRIP,ftperror);
  583.         FAMEReleaseConfig( myuserconf, FAMECFG_MODE_MODIFY, FindTask( NULL ));
  584.         FreePooled(mem_pool,fcr,sizeof(struct FAMEConfigRequest));
  585.          return(FALSE);
  586.         }
  587.   newbytes[0] = myuserconf->BytesUpHi;
  588.     newbytes[1] = myuserconf->BytesUpload;
  589.   FAMEAdd64(0UL,bytes,&newbytes);
  590.     myresult = FAMELockConfig(myuserconf);
  591.     if(myresult == FAMECFGRES_SUCCESS)
  592.         {
  593.         myuserconf->Uploads+=files;
  594.         myuserconf->BytesUpHi = newbytes[0];
  595.         myuserconf->BytesUpload = newbytes[1];
  596.         FAMEUnLockConfig(myuserconf);
  597.         }
  598.     else DebugLog("LockConfig(conf) Failed");
  599.     myresult = FAMESaveConfig(myuserconf,FAMECFG_MODE_MODIFY);
  600.     if(myresult != FAMECFGRES_SUCCESS)
  601.         {
  602.         DebugLog("Error writing back userconf.data: %ld",myresult);
  603.         }
  604.     FAMEReleaseConfig( myuserconf, FAMECFG_MODE_MODIFY, FindTask( NULL ));
  605.     FreePooled(mem_pool,fcr,sizeof(struct FAMEConfigRequest));
  606.     return(TRUE);
  607.     }
  608.  
  609. /*************************************************************************************************
  610.  *     FUNCTION: CheckIfOnline()
  611.  *      PURPOSE: Tests if given User is currently online
  612.  *        INPUT: unumcheck    => Usernumber to check for
  613.  *       RETURN: TRUE = User is online, FALSE = User is not online
  614.  *************************************************************************************************/
  615.  
  616. BOOL CheckIfOnline(long unumcheck)
  617.     {
  618.     struct  FAMESemaphore *MyFAMESemaphore;
  619.     struct     FAMEInfoList     *MyFAMEInfoList;
  620.     BOOL        isonline=FALSE;
  621.     long        usernumber;
  622.  
  623.     Forbid();
  624.     if(MyFAMESemaphore=(struct FAMESemaphore *)FindSemaphore("FAMESemaphore"))
  625.         {
  626.         ObtainSemaphore((struct SignalSemaphore *)MyFAMESemaphore);
  627.         Permit();
  628.         if(MyFAMESemaphore->fsem_FirstNode)
  629.             {
  630.       MyFAMEInfoList=MyFAMESemaphore->fsem_FirstNode;
  631.             do
  632.                 {
  633.           if((MyFAMEInfoList->fili_SVNodeOnline) && (MyFAMEInfoList->fili_UserOnline==2))
  634.                     {
  635.                     Forbid();
  636.                     usernumber = MyFAMEInfoList->fili_NodeRUser->UserNumber;
  637.                     Permit();
  638.                     if(usernumber == unumcheck)
  639.                         {
  640.                         isonline=TRUE;
  641.                         break;
  642.                         }
  643.             }
  644.                 MyFAMEInfoList=MyFAMEInfoList->fili_Next;
  645.                 }while(MyFAMEInfoList);
  646.             }
  647.         ReleaseSemaphore((struct SignalSemaphore *)MyFAMESemaphore);
  648.         }
  649.     else
  650.         {
  651.         Permit();
  652.         }
  653.     return(isonline);
  654.     }
  655.